using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Globalization;

namespace CodeStory.WebControls
{
	[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	public sealed class TreeNodeItemCollection : ICollection, IEnumerable, IStateManager
	{
		TreeNodeItem _parent;
		private bool isTrackingViewState;
		List<TreeNodeItem> list;

		internal TreeNodeItemCollection() {
			list = new List<TreeNodeItem>();
		}

		internal TreeNodeItemCollection(TreeNodeItem treeNodeItem):this() {
			_parent = treeNodeItem;
		}

		public TreeNodeItem this[int index]{
			get { return list[index]; }
			set { list[index] = value; }
		}

		public void CopyTo(Array array, int index) {
			((ICollection)list).CopyTo(array, index);
		}

		public int Count {
			get { return list.Count; }
		}

		internal void Add(TreeNodeItem node) {
			AddAt(this.Count,node);
		}

		private void AddAt(int index,TreeNodeItem node) {
			node.SetParent(this._parent);
			list.Insert(index,node);
			if (this.isTrackingViewState) {
				((IStateManager)node).TrackViewState();
				node.SetDirty();
			} 
			this.Log.Add(new LogItem(LogItemType.Insert, index, this.isTrackingViewState));
		}

		internal void Clear() {
			list.Clear(); 
			if (this.isTrackingViewState) {
				this.Log.Clear();
			}
			this.Log.Add(new LogItem(LogItemType.Clear, 0, this.isTrackingViewState));

		}
		public void Remove(TreeNodeItem value) {
			if (value == null) {
				throw new ArgumentNullException("value");
			}
			int index = this.list.IndexOf(value);
			if (index != -1) {
				this.RemoveAt(index);
			}
		}

		private void RemoveAt(int index) {
			TreeNodeItem node = this[index];
			this.list.RemoveAt(index);
			this.Log.Add(new LogItem(LogItemType.Remove, index, this.isTrackingViewState));
		}

		public object SyncRoot {
			get { return ((ICollection)list).SyncRoot; }
		}
		public bool IsSynchronized {
			get { return ((ICollection)list).IsSynchronized; }
		}

		public IEnumerator GetEnumerator() {
			foreach (TreeNodeItem it in list) {
				yield return it;
			}
		}

		#region ICollection Members

		void ICollection.CopyTo(Array array, int index) {
			if (!(array is TreeNodeItem[])) {
				throw new ArgumentException("TreeNodeCollection_InvalidArrayType");
			}
			this.list.CopyTo((TreeNodeItem[])array, index);
		}

		#endregion

		#region IEnumerable Members

		IEnumerator IEnumerable.GetEnumerator() {
			return GetEnumerator();
		}

		#endregion


		internal void SetDirty() {
			foreach (LogItem item in this.Log) {
				item.Tracked = true;
			}

			for (int i = 0; i < this.Count; i++) {
				this[i].SetDirty();
			}
		}

		#region IStateManager Members

		bool IStateManager.IsTrackingViewState {
			get { return this.isTrackingViewState; }
		}

		void IStateManager.LoadViewState(object state) {
			object[] objArray = (object[])state;
			if (objArray != null) {
				if (objArray[0] != null) {
					string[] strArray = ((string)objArray[0]).Split(new char[] { ',' });
					for (int j = 0; j < strArray.Length; j++) {
						string[] strArray2 = strArray[j].Split(new char[] { ':' });
						LogItemType type = (LogItemType)int.Parse(strArray2[0], CultureInfo.InvariantCulture);
						int index = int.Parse(strArray2[1], CultureInfo.InvariantCulture);
						switch (type) {
							case LogItemType.Remove:
								this.RemoveAt(index);
								break;

							case LogItemType.Clear:
								this.Clear();
								break;

							case LogItemType.Insert:
								if ((this._parent != null) && (this._parent.TreeGrid != null)) {
									this.AddAt(index, this._parent.TreeGrid.CreateNode());
								} else {
									this.AddAt(index, new TreeNodeItem());
								}
								break;
						}
					}
				}
				for (int i = 0; i < (objArray.Length - 1); i++) {
					if ((objArray[i + 1] != null) && (this[i] != null)) {
						((IStateManager)this[i]).LoadViewState(objArray[i + 1]);
					}
				}
			}
		}

		object IStateManager.SaveViewState() {
			object[] objArray = new object[this.Count + 1];
			bool flag = false;
			if ((this._log != null) && (this._log.Count > 0)) {
				StringBuilder builder = new StringBuilder();
				int num = 0;
				for (int j = 0; j < this._log.Count; j++) {
					LogItem item = this._log[j];
					if (item.Tracked) {
						builder.Append((int)item.Type);
						builder.Append(":");
						builder.Append(item.Index);
						if (j < (this._log.Count - 1)) {
							builder.Append(",");
						}
						num++;
					}
				}
				if (num > 0) {
					objArray[0] = builder.ToString();
					flag = true;
				}
			}
			for (int i = 0; i < this.Count; i++) {
				objArray[i + 1] = ((IStateManager)this[i]).SaveViewState();
				if (objArray[i + 1] != null) {
					flag = true;
				}
			}
			if (!flag) {
				return null;
			}
			return objArray;

		}

		void IStateManager.TrackViewState() {
			isTrackingViewState = true;
			for (int i = 0; i < this.Count; i++) {
				this[i].TrackViewState();
			}
		}

		#endregion

		private class LogItem
		{
			// Fields
			private int _index;
			private bool _tracked;
			private LogItemType _type;

			// Methods
			public LogItem(LogItemType type, int index, bool tracked) {
				this._type = type;
				this._index = index;
				this._tracked = tracked;
			}

			// Properties
			public int Index {
				get {
					return this._index;
				}
			}

			public bool Tracked {
				get {
					return this._tracked;
				}
				set {
					this._tracked = value;
				}
			}

			public LogItemType Type {
				get {
					return this._type;
				}
			}
		}
		private enum LogItemType
		{
			Insert,
			Remove,
			Clear
		}
		private List<LogItem> _log;
		private List<LogItem> Log {
			get {
				if (this._log == null) {
					this._log = new List<LogItem>();
				}
				return this._log;
			}
		}
	}
}